package salomon.model 
{
	
	import flash.display.DisplayObjectContainer;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import salomon.event.SimpleModelEvent;
	import salomon.model.vo.SimpleModelVO;
	import salomon.type.SimpleModelType;
	import salomon.utils.Alert;
	/**
	 * <p>Modelo responsável por carregamento único de arquivo, utiliza Loader como base.</p>
	 * <p>Autor Tiago Salomon</p>
	 * 
	 * @author Tiago Salomon
	 */	
	public class SimpleModel extends EventDispatcher
	{
		/**
		 * Dados do modelo.
		 */
		private var _data		: SimpleModelVO;
		/**
		 * Loader utilizado no carregamento de midia.
		 */
		private var _loader		: Loader;
		/**
		 * URLLoader utilizado no carregamento de dados.
		 */
		private var _urlLoader	: URLLoader;
		/**
		 * Configura se o debug está ativo ou não.
		 * @default false
		 */
		private var _debug		: Boolean	= false;
		/**
		 * Armazena o id do Model, será exibido com o debugger.
		 * @default Default
		 */
		private var _id			: String	= "Default";
		/**
		 * Alvo onde o conteúdo carregado será adicionado.
		 */
		private var _container	: DisplayObjectContainer;
		/**
		 * URL do carregamento.
		 */
		private var _path		: String;
		/**
		 * Tipo de carregamento Ex: SimpleModelType.DATA, SimpleModelType.DISPLAY.
		 */
		private var _type		: String;
		/**
		 * Modelo que faz o carregamento de um item.
		 * @param	id		String
		 * @param	type	String  Ex: SimpleModelType.DATA, SimpleModelType.DISPLAY
		 * @param 	debug	Boolean
		 */
		public function SimpleModel(id:String, type:String, debug:Boolean = false) 
		{
			_type = type;
			this._id 	= id;
			this._debug = debug;
			
			this._data = new SimpleModelVO();
			
			if (type == SimpleModelType.DISPLAY)
			{
				this._loader = new Loader();
				this._loader.contentLoaderInfo.addEventListener(Event.OPEN, onStart);					
				this._loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
				this._loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
				this._loader.contentLoaderInfo.addEventListener(Event.UNLOAD, onUnload);
				this._loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);				
			}
			else if (type == SimpleModelType.DATA)
			{
				this._urlLoader = new URLLoader();
				this._urlLoader.addEventListener(Event.OPEN, onStart);
				this._urlLoader.addEventListener(ProgressEvent.PROGRESS, onProgress);
				this._urlLoader.addEventListener(Event.COMPLETE, onComplete);
				this._urlLoader.addEventListener(Event.UNLOAD, onUnload);
				this._urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
			}	
		}
		/**
		 * Trata o erro ao não conseguir carregar o arquivo.
		 * @param	e	IOErrorEvent
		 */
		private function onError(e:IOErrorEvent):void 
		{
			if (this._debug)
			{
				Alert.to("\n SIMPLE MODEL " + this._id + " >> NÃO FOI POSSÍVEL CARREGAR: " + this._path);
			}
		}
		
		/**
		 * Handler de inicio de carregamento.
		 * @param	e	Event
		 */
		private function onStart(e:Event):void 
		{
			e.stopPropagation();
			
			if (this._debug) 
				Alert.to("SIMPLE MODEL " + this._id + " >> START.");
		}	
		/**
		 * Handler de progresso do carregamento.
		 * @param	e	ProgressEvent
		 */
		private function onProgress(e:ProgressEvent):void 
		{
			e.stopPropagation();
			
			if (this._debug) 
				Alert.to("SIMPLE MODEL " + this._id + " >> LOAD " + Math.round((e.bytesLoaded / e.bytesTotal * 100)).toString() + "% COMPLETE.");	
				
			this._data.percentage = Math.round((e.bytesLoaded / e.bytesTotal * 100));

			this.dispatchEvent(new SimpleModelEvent(SimpleModelEvent.PROGRESS));			
		}		
		/**
		 * Handler de carregamento completo.
		 * @param	e	Event
		 */
		private function onComplete(e:Event):void 
		{
			e.stopPropagation();
			
			if (this._debug) 
				Alert.to("SIMPLE MODEL "+this._id+" >> QUEUE COMPLETE.");
				
			if (this._type == SimpleModelType.DISPLAY)
			{
				this._data.content = e.target.content;
			
				if (this._container != null)
				{
					this._container.addChild(this._loader);
				}
			}
			else if (this._type == SimpleModelType.DATA)
			{
				this._data.content = this._urlLoader.data;
			}
			
			this.dispatchEvent(new SimpleModelEvent(SimpleModelEvent.COMPLETE));
		}
		/**
		 * Responsável pelo carregamento.
		 * @param	path		String
		 * @param	container	DisplayObjectContainer
		 * @param	checkPolicyFile	Boolean
		 */
		public function load(path:String, container:DisplayObjectContainer = null, checkPolicyFile:Boolean = false):void
		{			
			this._path = path;
			this._container = container;
			
			if (this._type == SimpleModelType.DISPLAY)
			{
				var context:LoaderContext = new LoaderContext();
					context.checkPolicyFile = checkPolicyFile;
				
				this._loader.load(new URLRequest(path), context);				
			}
			else if (this._type == SimpleModelType.DATA)
			{
				this._urlLoader.load(new URLRequest(path));
			}
		}
		/**
		 * Destrói os dados do modelo.
		 */
		public function dispose():void 
		{
			if (this._debug) 
				Alert.to("SIMPLE MODEL " + this._id + " >> DISPOSE");
				
			if (this._type == SimpleModelType.DISPLAY)
			{
				this._loader.unloadAndStop();
				this._loader.unload();	
			}
			else if (this._type == SimpleModelType.DATA)
			{
				this._urlLoader.close()
			}
			this._data.destroy();			
		}
		/**
		 * Destroy o modelo.
		 */
		public function destroy():void 
		{
			if (this._debug) 
				Alert.to("SIMPLE MODEL " + this._id + " >> DESTROY");	
			
			if (this._type == SimpleModelType.DISPLAY)
			{
				this._loader.contentLoaderInfo.removeEventListener(Event.INIT, onStart);
				this._loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
				this._loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);				
				this._loader.unloadAndStop();
				this._loader.unload();
				this._loader = null;
			}
			else if (this._type == SimpleModelType.DATA)
			{
				this._urlLoader.removeEventListener(Event.OPEN, onStart);
				this._urlLoader.removeEventListener(ProgressEvent.PROGRESS, onProgress);
				this._urlLoader.removeEventListener(Event.COMPLETE, onComplete);
				this._urlLoader.removeEventListener(Event.UNLOAD, onUnload);
				this._urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, onError);
				this._urlLoader.close();
				this._urlLoader = null;
			}
			
			this._data.destroy();
		}
		/**
		 * Handler disparado ao descarregar o modelo.
		 * @param	e	Event
		 */	
		private function onUnload(e:Event):void 
		{			
			if (this._debug)
				Alert.to("SIMPLE MODEL >> UNLOAD");
				
			this._loader.unloadAndStop(true);
		}		
		/**
		 * Retorna os dados carregados pelo SimpleModel.
		 */
		public function get data():SimpleModelVO 
		{
			return _data;
		}
		
	} 
}